home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 176-200 / scopedisk191 / lightpen / lp.c < prev    next >
C/C++ Source or Header  |  1995-03-19  |  8KB  |  256 lines

  1. /*************************************************
  2. *       Name :       lightpen
  3. * This code installs a lightpendriver as an
  4. * InputEvent-Handler.
  5. * Left  Mousebutton on Pin 3
  6. * Right Mousebutton on Pin 4
  7. *
  8. * For SAS/C compile with -v
  9. * (no stack checking)
  10. *
  11. *    © Copyright by Andreas Klingler 1988,1991
  12. *
  13. * This program is freely distributable but is NOT public domain.
  14. * It MAY NOT be included in any commercial package, or sold for
  15. * ANY amount, without written permission from the author.
  16. * However if may be included on any freely distributable package,
  17. * including packages for which a nominal copying fee of no more than
  18. * $5 is charged, as long as this copyright notice keeps intact.
  19. * This software is distributed as-is, without any warranty.
  20. *
  21. *          created 31.10.88 akk
  22. *          cleanup 27.01.91 akk
  23. *************************************************/
  24. #include <exec/types.h>
  25. #include "intuition/intuition.h"
  26. #include <exec/ports.h>
  27. #include <exec/io.h>
  28. #include <exec/memory.h>
  29. #include <devices/input.h>
  30. #include <exec/devices.h>
  31. #include <devices/inputevent.h>
  32. #include "stdio.h"
  33. #include "stdlib.h"
  34. #include "graphics/gfxbase.h"
  35. #include "graphics/view.h"
  36. #include "proto/dos.h"
  37. #include "proto/exec.h"
  38. #include "proto/intuition.h"
  39. #include "proto/graphics.h"
  40. #include "hardware/custom.h"
  41.  
  42. /***************** CONSTANTS ********************/
  43. #define LP_ENABLE 0x08
  44. #define XCOMPENSATE 42 /* This is to compensate some timing problems.
  45.               You might need to change this. Uh! Again the
  46.               answer is 42! What was the question!? */
  47.  
  48. #define BANNER "\x9B\x30;33mLightpenhandler Version 1.1\x9B\x30m © by Andreas Klingler 1988,1991\n"
  49. #define ACTIVATED " Handler installed\n"
  50. #define TERMINATING " Handler removed\n"
  51. #define PORTNAME "lightpen_AKK.port"
  52.  
  53. /****************** GLOBAL VARIABLES ************/
  54. extern struct Custom __far custom;
  55.  
  56. struct MsgPort *inputDevPort;
  57. struct IOStdReq *inputRequestBlock;
  58. struct Interrupt handlerStuff;
  59. struct OURMSG {
  60.     struct Message msgpart;
  61.     short dummy;
  62.     } msg;
  63.  
  64. struct LpInfo { short *ViewX, *ViewY;  } handlerdata;
  65.  
  66. /* Prototypes for functions defined in lp.c */
  67. struct InputEvent * __regargs __saveds myhandler(struct InputEvent *,
  68.                                                  struct LpInfo *);
  69. void main(void);
  70. void chkabort(void);
  71.  
  72.  
  73. /* Declarations for CBACK */
  74. extern BPTR _Backstdout;         /* standard output when run in background */
  75. long _BackGroundIO = 1;          /* Flag to tell it we want to do I/O      */
  76. long _stack = 4000;              /* Amount of stack space our task needs   */
  77. char *_procname = "Lightpenhandler";  /* The name of the task to create    */
  78. long _priority = 20;             /* The priority to run us at              */
  79.  
  80. /******************* Here goes the Handler ****************/
  81. struct InputEvent *
  82. __regargs __saveds myhandler(ev, mydata)
  83.     struct InputEvent *ev;  /* and a pointer to a list of events */
  84.     struct LpInfo *mydata;  /* system will pass me a pointer to my 
  85.                       own data space. */
  86.         
  87.     static struct InputEvent lpev; 
  88.     struct InputEvent *retwert;
  89.     BOOL lpen_invalid = FALSE,button_pressed = FALSE;
  90.     static BOOL left_down,right_down;
  91.     ULONG pos;
  92.     static ULONG *lpen = (ULONG *)&custom.vposr;
  93.     register short x,y;
  94.  
  95.     pos = *lpen;    /* read pen position (we read two
  96.                registers here: VPOSR,VHPOSR) */
  97.  
  98.     Forbid();
  99.       if ((pos != *lpen) || /* Test, if Lpen has been
  100.                    triggered since VBLANK */
  101.          ((pos & 0x1ffff) > 0x12a00)) {  retwert=ev; lpen_invalid=TRUE; }
  102.        else retwert = &lpev;
  103.  
  104.     /* Translate in HIRES INLACE coordinates (depending of position of
  105.        the View). That`s what mouse coordinates are in.
  106.        Since we have only 8 bits for the horizonal position it gets
  107.        a little bit tricky (there are 640 pixel in one line in hires!) */
  108.       x = (short)((pos <<1) & 0x1ff);
  109.       if (x < 100) x += 454;
  110.        y = ((short) (pos >> 8) &0x1ff) - *(mydata->ViewY);
  111.        x -= (*(mydata->ViewX) + XCOMPENSATE);
  112.  
  113.       lpev.ie_NextEvent = ev;  /* link lpen ahead of event stream */
  114.       lpev.ie_Class = IECLASS_POINTERPOS;
  115.       lpev.ie_Code = IECODE_NOBUTTON;
  116.       lpev.ie_Qualifier = 0;
  117.       lpev.ie_TimeStamp.tv_secs = 0;
  118.       lpev.ie_TimeStamp.tv_micro = 0;
  119.       lpev.ie_X = x << 1;
  120.       lpev.ie_Y = y << 1;
  121.  
  122.     /* Button on lightpen pressed ? */
  123.       if (right_down) {
  124.           if (!(custom.joy1dat & 1)) { lpev.ie_Code = IECODE_RBUTTON |
  125.                                   IECODE_UP_PREFIX;
  126.                            right_down = FALSE;
  127.                          button_pressed = TRUE;
  128.                        }
  129.                 }
  130.       else if (custom.joy1dat & 1) { lpev.ie_Code = IECODE_RBUTTON;
  131.                          right_down = TRUE;
  132.                      button_pressed = TRUE;
  133.                     }
  134.       if (left_down) {
  135.               if (!(custom.joy1dat & 0x100)){
  136.                     lpev.ie_Code = IECODE_LBUTTON |
  137.                                IECODE_UP_PREFIX;
  138.                     left_down = FALSE;
  139.                     button_pressed = TRUE;
  140.                     }
  141.                 }
  142.         else    if (custom.joy1dat & 0x100) {
  143.                     lpev.ie_Code = IECODE_LBUTTON;
  144.                     left_down = TRUE;
  145.                     button_pressed = TRUE;
  146.                     }
  147.  
  148.     /* Append positiondata only if it is valid */
  149.       if (button_pressed && lpen_invalid) {
  150.             lpev.ie_Class = IECLASS_RAWMOUSE;
  151.             lpev.ie_Qualifier = IEQUALIFIER_RELATIVEMOUSE;
  152.             lpev.ie_X = lpev.ie_Y = 0; 
  153.             retwert = &lpev;
  154.             }
  155.     Permit();
  156.     return (retwert);
  157. }
  158.  
  159.  
  160. void main()
  161. {
  162.     struct MsgPort *port;
  163.     SHORT error;
  164.  
  165.  
  166.     if (_Backstdout) Write(_Backstdout, BANNER, sizeof(BANNER));
  167.  
  168.     /* now see if we are allready installed */
  169.       if (!(port = FindPort(PORTNAME)))  {
  170.         /* if not, install ourself : */
  171.     if ((port = CreatePort(PORTNAME,0)) == NULL) _exit (19);
  172.  
  173.     GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0);
  174.     if (!GfxBase) _exit(20);
  175.     
  176.     IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0);
  177.     if (!IntuitionBase) _exit(21);
  178.             
  179.     /* Tell the OS about the lightpen and enable the hardware */
  180.     GfxBase->system_bplcon0 |= LP_ENABLE;
  181.     RemakeDisplay();
  182.  
  183.     /* Determine position of the View. Attention: if someone pokes
  184.        around with Preferences while we are running, we can`t handle
  185.        this! */           
  186.     handlerdata.ViewX = (short *)&(GfxBase->ActiView->DxOffset);
  187.     handlerdata.ViewY = (short *)&(GfxBase->ActiView->DyOffset);
  188.  
  189.     inputDevPort = CreatePort(0,0);        /* for input device */
  190.     if(inputDevPort == NULL) _exit(1);    /* error during createport */
  191.     inputRequestBlock=CreateStdIO(inputDevPort);
  192.     if(inputRequestBlock == 0) { DeletePort(inputDevPort); _exit(2); }
  193.                     /* error during createstdio */
  194.  
  195.  
  196.     handlerStuff.is_Data = (APTR)&handlerdata;
  197.             /* address of its data area */
  198.     handlerStuff.is_Code = (void *)myhandler;
  199.             /* address of entry point to handler */
  200.     handlerStuff.is_Node.ln_Pri = 51;
  201.             /* set the priority one step higher than
  202.               * Intuition, so that our handler enters
  203.              * the chain ahead of Intuition.
  204.              */
  205.     error = OpenDevice("input.device",0,(struct IORequest *)inputRequestBlock,0);
  206.     if(error) _exit(23);
  207.  
  208.     inputRequestBlock->io_Command = IND_ADDHANDLER;
  209.     inputRequestBlock->io_Data = (APTR)&handlerStuff;
  210.         
  211.     DoIO((struct IORequest *)inputRequestBlock);  /* Activate the Handler */
  212.     
  213.     /* The Handler is running. Close everything we don`t need
  214.        anymore and wait until it is time to uninstall the handler.
  215.        All the dirty work is done by the handler */
  216.  
  217.     CloseLibrary((struct Library *)IntuitionBase);
  218.     CloseLibrary((struct Library *)GfxBase);
  219.  
  220.     if (_Backstdout) { Write(_Backstdout,ACTIVATED, sizeof(ACTIVATED));
  221.                Close(_Backstdout);
  222.                }
  223.     WaitPort(port);          /* Wait until we get message */
  224.     GetMsg(port);            /* to exit, then remove it */
  225.                     /* and get out           */
  226.  
  227.     inputRequestBlock->io_Command = IND_REMHANDLER;
  228.     inputRequestBlock->io_Data = (APTR)&handlerStuff;
  229.     DoIO((struct IORequest *)inputRequestBlock);
  230.  
  231.     /* close the input device */
  232.     CloseDevice((struct IORequest *)inputRequestBlock);
  233.  
  234.     /* delete the IO request */
  235.     DeleteStdIO(inputRequestBlock);
  236.  
  237.     /* free other system stuff */
  238.     DeletePort(inputDevPort);
  239.     DeletePort(port);
  240.       }   /* this is the end of the BIG-IF (and of the program */
  241.  
  242.       else  /* in this case the handler is already installed, so we
  243.            send a message to it to make it deinstall itself */
  244.     {
  245.     msg.msgpart.mn_Length = sizeof(struct OURMSG);
  246.     PutMsg(port,(struct Message *)&msg);
  247.     if (_Backstdout) { Write(_Backstdout, TERMINATING, sizeof(TERMINATING));
  248.                Close(_Backstdout);
  249.                }
  250.        }
  251. }                    /* end of main */
  252.  
  253. void MemCleanup() {}    /* We don`t want this out of lc.lib */
  254.  
  255. void chkabort() {}